1
2
3
4 package joeq.ClassLib.Common.java.util.zip;
5
6 /***
7 * Deflater
8 *
9 * @author John Whaley <jwhaley@alum.mit.edu>
10 * @version $Id: Deflater.java 1451 2004-03-09 06:27:08Z jwhaley $
11 */
12 public class Deflater {
13
14 private static void initIDs() { }
15
16 /***
17 * The best and slowest compression level. This tries to find very
18 * long and distant string repetitions.
19 */
20 public static final int BEST_COMPRESSION = 9;
21 /***
22 * The worst but fastest compression level.
23 */
24 public static final int BEST_SPEED = 1;
25 /***
26 * The default compression level.
27 */
28 public static final int DEFAULT_COMPRESSION = -1;
29 /***
30 * This level won't compress at all but output uncompressed blocks.
31 */
32 public static final int NO_COMPRESSION = 0;
33
34 /***
35 * The default strategy.
36 */
37 public static final int DEFAULT_STRATEGY = 0;
38 /***
39 * This strategy will only allow longer string repetitions. It is
40 * useful for random data with a small character set.
41 */
42 public static final int FILTERED = 1;
43
44 /***
45 * This strategy will not look for string repetitions at all. It
46 * only encodes with Huffman trees (which means, that more common
47 * characters get a smaller encoding.
48 */
49 public static final int HUFFMAN_ONLY = 2;
50
51 /***
52 * The compression method. This is the only method supported so far.
53 * There is no need to use this constant at all.
54 */
55 public static final int DEFLATED = 8;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 private static final int IS_SETDICT = 0x01;
93 private static final int IS_FLUSHING = 0x04;
94 private static final int IS_FINISHING = 0x08;
95
96 private static final int INIT_STATE = 0x00;
97 private static final int SETDICT_STATE = 0x01;
98 private static final int INIT_FINISHING_STATE = 0x08;
99 private static final int SETDICT_FINISHING_STATE = 0x09;
100 private static final int BUSY_STATE = 0x10;
101 private static final int FLUSHING_STATE = 0x14;
102 private static final int FINISHING_STATE = 0x1c;
103 private static final int FINISHED_STATE = 0x1e;
104 private static final int CLOSED_STATE = 0x7f;
105
106 /*** Compression level. */
107 private int level;
108
109 /*** should we include a header. */
110 private boolean noHeader;
111
112 /*** Compression strategy. */
113 private int strategy;
114
115 /*** The current state. */
116 private int state;
117
118 /*** The total bytes of output written. */
119 private int totalOut;
120
121 /*** The pending output. */
122 private DeflaterPending pending;
123
124 /*** The deflater engine. */
125 private DeflaterEngine engine;
126
127 /***
128 * Creates a new deflater with default compression level.
129 */
130 public Deflater()
131 {
132 this(DEFAULT_COMPRESSION, false);
133 }
134
135 /***
136 * Creates a new deflater with given compression level.
137 * @param lvl the compression level, a value between NO_COMPRESSION
138 * and BEST_COMPRESSION, or DEFAULT_COMPRESSION.
139 * @exception IllegalArgumentException if lvl is out of range.
140 */
141 public Deflater(int lvl)
142 {
143 this(lvl, false);
144 }
145
146 /***
147 * Creates a new deflater with given compression level.
148 * @param lvl the compression level, a value between NO_COMPRESSION
149 * and BEST_COMPRESSION.
150 * @param nowrap true, iff we should suppress the deflate header at the
151 * beginning and the adler checksum at the end of the output. This is
152 * useful for the GZIP format.
153 * @exception IllegalArgumentException if lvl is out of range.
154 */
155 public Deflater(int lvl, boolean nowrap)
156 {
157 if (lvl == DEFAULT_COMPRESSION)
158 lvl = 6;
159 else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION)
160 throw new IllegalArgumentException();
161
162 pending = new DeflaterPending();
163 engine = new DeflaterEngine(pending);
164 this.noHeader = nowrap;
165 setStrategy(DEFAULT_STRATEGY);
166 setLevel(lvl);
167 reset();
168 }
169
170 /***
171 * Resets the deflater. The deflater acts afterwards as if it was
172 * just created with the same compression level and strategy as it
173 * had before.
174 */
175 public void reset()
176 {
177 state = (noHeader ? BUSY_STATE : INIT_STATE);
178 totalOut = 0;
179 pending.reset();
180 engine.reset();
181 }
182
183 /***
184 * Frees all objects allocated by the compressor. There's no
185 * reason to call this, since you can just rely on garbage
186 * collection. Exists only for compatibility against Sun's JDK,
187 * where the compressor allocates native memory.
188 * If you call any method (even reset) afterwards the behaviour is
189 * <i>undefined</i>.
190 * @deprecated Just clear all references to deflater instead.
191 */
192 public void end()
193 {
194 engine = null;
195 pending = null;
196 state = CLOSED_STATE;
197 }
198
199 /***
200 * Gets the current adler checksum of the data that was processed so
201 * far.
202 */
203 public int getAdler()
204 {
205 return engine.getAdler();
206 }
207
208 /***
209 * Gets the number of input bytes processed so far.
210 */
211 public int getTotalIn()
212 {
213 return engine.getTotalIn();
214 }
215
216 /***
217 * Gets the number of output bytes so far.
218 */
219 public int getTotalOut()
220 {
221 return totalOut;
222 }
223
224 /***
225 * Finalizes this object.
226 */
227 protected void finalize() throws Throwable
228 {
229
230 super.finalize();
231 }
232
233 /***
234 * Flushes the current input block. Further calls to deflate() will
235 * produce enough output to inflate everything in the current input
236 * block. This is not part of Sun's JDK so I have made it package
237 * private. It is used by DeflaterOutputStream to implement
238 * flush().
239 */
240 void flush() {
241 state |= IS_FLUSHING;
242 }
243
244 /***
245 * Finishes the deflater with the current input block. It is an error
246 * to give more input after this method was called. This method must
247 * be called to force all bytes to be flushed.
248 */
249 public void finish() {
250 state |= IS_FLUSHING | IS_FINISHING;
251 }
252
253 /***
254 * Returns true iff the stream was finished and no more output bytes
255 * are available.
256 */
257 public boolean finished()
258 {
259 return state == FINISHED_STATE && pending.isFlushed();
260 }
261
262 /***
263 * Returns true, if the input buffer is empty.
264 * You should then call setInput(). <br>
265 *
266 * <em>NOTE</em>: This method can also return true when the stream
267 * was finished.
268 */
269 public boolean needsInput()
270 {
271 return engine.needsInput();
272 }
273
274 /***
275 * Sets the data which should be compressed next. This should be only
276 * called when needsInput indicates that more input is needed.
277 * If you call setInput when needsInput() returns false, the
278 * previous input that is still pending will be thrown away.
279 * The given byte array should not be changed, before needsInput() returns
280 * true again.
281 * This call is equivalent to <code>setInput(input, 0, input.length)</code>.
282 * @param input the buffer containing the input data.
283 * @exception IllegalStateException if the buffer was finished() or ended().
284 */
285 public void setInput(byte[] input)
286 {
287 setInput(input, 0, input.length);
288 }
289
290 /***
291 * Sets the data which should be compressed next. This should be
292 * only called when needsInput indicates that more input is needed.
293 * The given byte array should not be changed, before needsInput() returns
294 * true again.
295 * @param input the buffer containing the input data.
296 * @param off the start of the data.
297 * @param len the length of the data.
298 * @exception IllegalStateException if the buffer was finished() or ended()
299 * or if previous input is still pending.
300 */
301 public void setInput(byte[] input, int off, int len)
302 {
303 if ((state & IS_FINISHING) != 0)
304 throw new IllegalStateException("finish()/end() already called");
305 engine.setInput(input, off, len);
306 }
307
308 /***
309 * Sets the compression level. There is no guarantee of the exact
310 * position of the change, but if you call this when needsInput is
311 * true the change of compression level will occur somewhere near
312 * before the end of the so far given input.
313 * @param lvl the new compression level.
314 */
315 public void setLevel(int lvl)
316 {
317 if (lvl == DEFAULT_COMPRESSION)
318 lvl = 6;
319 else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION)
320 throw new IllegalArgumentException();
321
322
323 if (level != lvl)
324 {
325 level = lvl;
326 engine.setLevel(lvl);
327 }
328 }
329
330 /***
331 * Sets the compression strategy. Strategy is one of
332 * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact
333 * position where the strategy is changed, the same as for
334 * setLevel() applies.
335 * @param stgy the new compression strategy.
336 */
337 public void setStrategy(int stgy)
338 {
339 if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
340 && stgy != HUFFMAN_ONLY)
341 throw new IllegalArgumentException();
342 engine.setStrategy(stgy);
343 }
344
345 /***
346 * Deflates the current input block to the given array. It returns
347 * the number of bytes compressed, or 0 if either
348 * needsInput() or finished() returns true or length is zero.
349 * @param output the buffer where to write the compressed data.
350 */
351 public int deflate(byte[] output)
352 {
353 return deflate(output, 0, output.length);
354 }
355
356 /***
357 * Deflates the current input block to the given array. It returns
358 * the number of bytes compressed, or 0 if either
359 * needsInput() or finished() returns true or length is zero.
360 * @param output the buffer where to write the compressed data.
361 * @param offset the offset into the output array.
362 * @param length the maximum number of bytes that may be written.
363 * @exception IllegalStateException if end() was called.
364 * @exception IndexOutOfBoundsException if offset and/or length
365 * don't match the array length.
366 */
367 public int deflate(byte[] output, int offset, int length)
368 {
369 int origLength = length;
370
371 if (state == CLOSED_STATE)
372 throw new IllegalStateException("Deflater closed");
373
374 if (state < BUSY_STATE)
375 {
376
377 int header = (DEFLATED +
378 ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
379 int level_flags = (level - 1) >> 1;
380 if (level_flags < 0 || level_flags > 3)
381 level_flags = 3;
382 header |= level_flags << 6;
383 if ((state & IS_SETDICT) != 0)
384
385 header |= DeflaterConstants.PRESET_DICT;
386 header += 31 - (header % 31);
387
388 pending.writeShortMSB(header);
389 if ((state & IS_SETDICT) != 0)
390 {
391 int chksum = engine.getAdler();
392 engine.resetAdler();
393 pending.writeShortMSB(chksum >> 16);
394 pending.writeShortMSB(chksum & 0xffff);
395 }
396
397 state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
398 }
399
400 for (;;)
401 {
402 int count = pending.flush(output, offset, length);
403 offset += count;
404 totalOut += count;
405 length -= count;
406 if (length == 0 || state == FINISHED_STATE)
407 break;
408
409 if (!engine.deflate((state & IS_FLUSHING) != 0,
410 (state & IS_FINISHING) != 0))
411 {
412 if (state == BUSY_STATE)
413
414 return origLength - length;
415 else if (state == FLUSHING_STATE)
416 {
417 if (level != NO_COMPRESSION)
418 {
419
420
421
422
423 int neededbits = 8 + ((-pending.getBitCount()) & 7);
424 while (neededbits > 0)
425 {
426
427
428
429 pending.writeBits(2, 10);
430 neededbits -= 10;
431 }
432 }
433 state = BUSY_STATE;
434 }
435 else if (state == FINISHING_STATE)
436 {
437 pending.alignToByte();
438
439 if (!noHeader)
440 {
441 int adler = engine.getAdler();
442 pending.writeShortMSB(adler >> 16);
443 pending.writeShortMSB(adler & 0xffff);
444 }
445 state = FINISHED_STATE;
446 }
447 }
448 }
449
450 return origLength - length;
451 }
452
453 /***
454 * Sets the dictionary which should be used in the deflate process.
455 * This call is equivalent to <code>setDictionary(dict, 0,
456 * dict.length)</code>.
457 * @param dict the dictionary.
458 * @exception IllegalStateException if setInput () or deflate ()
459 * were already called or another dictionary was already set.
460 */
461 public void setDictionary(byte[] dict)
462 {
463 setDictionary(dict, 0, dict.length);
464 }
465
466 /***
467 * Sets the dictionary which should be used in the deflate process.
468 * The dictionary should be a byte array containing strings that are
469 * likely to occur in the data which should be compressed. The
470 * dictionary is not stored in the compressed output, only a
471 * checksum. To decompress the output you need to supply the same
472 * dictionary again.
473 * @param dict the dictionary.
474 * @param offset an offset into the dictionary.
475 * @param length the length of the dictionary.
476 * @exception IllegalStateException if setInput () or deflate () were
477 * already called or another dictionary was already set.
478 */
479 public void setDictionary(byte[] dict, int offset, int length)
480 {
481 if (state != INIT_STATE)
482 throw new IllegalStateException();
483
484 state = SETDICT_STATE;
485 engine.setDictionary(dict, offset, length);
486 }
487 }